import Canvas from "canvas";
import Path from "path";
import Fs from "fs";
import Quantize from "quantize";
import Potrace from "potrace";
import { gap } from "./quantize-gap.js";
// import { slicTest } from "./slic.js";
import { loadLocalImage } from "./ResourceLoader.js";
import { colorDistance, colorRgb, colorHex, getNearColorIndex } from "./ColorUtils.js";

// 位图转为矢量图
const getSvgPath = (width, height, buffer, color) => {
    const option = {
        turnPolicy: Potrace.Potrace.TURNPOLICY_MINORITY, // - how to resolve ambiguities in path decomposition (default Potrace.TURNPOLICY_MINORITY)
        turdSize: 5, // - suppress speckles of up to this size (default 2)
        alphaMax: 1, // - corner threshold parameter (default 1)
        optCurve: true, // - curve optimization (default true)
        optTolerance: 0.2, // - curve optimization tolerance (default 0.2)
        threshold: 200, // - threshold below which color is considered black (0..255, default Potrace.THRESHOLD_AUTO)
        blackOnWhite: true, // - specifies colors by which side from threshold should be traced (default true)
        width: width,
        height: height,
        color: color, // - foreground color (default: 'auto' (black or white)) Will be ignored when exporting as <symbol>
        background: "transparent", // - background color (default: 'transparent') Will be ignored when exporting as <symbol>
    };

    return new Promise((resolve, reject) => {
        const potrace = new Potrace.Potrace(option);
        potrace.loadImage(buffer, err => {
            if (err) {
                reject(err);
            } else {
                resolve(potrace.getPathTag());
            }
        });
    });
};

// 获取rgb
const getImageData = image => {
    const canvas = Canvas.createCanvas(image.width, image.height);
    const ctx = canvas.getContext("2d");

    // 粘贴图片
    ctx.drawImage(image, 0, 0, image.width, image.height);

    // 提取颜色
    const pixels = ctx.getImageData(0, 0, canvas.width, canvas.height).data;

    return pixels;
};

// 获取主色
const getBaseColors = (pixels, colors) => {
    const size = Math.round(pixels.length / 4);
    const rgb = [];
    
    for (let i = 0, offset, r, g, b, a; i < size; i++) {
        offset = i * 4;
        r = pixels[offset + 0];
        g = pixels[offset + 1];
        b = pixels[offset + 2];
        a = pixels[offset + 3];

        if (typeof a === "undefined" || a >= 200) {
            rgb.push([r, g, b]);
            // if (!(r > 250 && g > 250 && b > 250)) {
            //     rgb.push([r, g, b]);
            // }
        }
    }


    // 获取主色
    // const cmap = Quantize(rgb, colors.length);
    const cmap = Quantize(rgb, 4);

    const palette = cmap ? cmap.palette() : [];

    const repeat = new Map(palette.map(i => [i.join(","), i]));

    // 把主题色替换为目标色
    // const result = palette.map(rgb => {
    //     const distance = colors.map(color => colorDistance(rgb, color.rgb));
    //     const min = Math.min(...distance);
    //     const index = distance.indexOf(min);
    //     const active = colors[index];

    //     return {
    //         rgb: rgb,
    //         hex: colorHex(rgb),
    //         fill: active ? active.hex : undefined,
    //     };
    // });

    // const result = Array.from(repeat.values()).map(rgb => ({
    //     rgb: rgb,
    //     hex: colorHex(rgb),
    //     fill: colorHex(rgb),
    // }));

    cmap.vboxes.map(i => console.log("cmap.vboxes",i.vbox._count, i.vbox._volume));
    return Array.from(repeat.values());
};

// 取图形
/**
 * @param pixels 像素点
 * @param colors 主色
 * @param place 针线颜色
 */
const getShapePaths = async (width, height, pixels, colors, place) => {
    const size = width * height;

    const places = place.map(i => i.rgb);

    // 图层分离
    const layers = colors.map(rgb => {
        const canvas = Canvas.createCanvas(width, height);
        const ctx = canvas.getContext("2d");
        const pixel = ctx.createImageData(width, height);
        const index = getNearColorIndex(rgb, places);
        const active = place[index];

        return {
            width: width,
            height: height,
            canvas: canvas,
            ctx: ctx,
            pixel: pixel,
            rgb: rgb,
            hex: colorHex(rgb),
            // fill: active ? active.fill : colorHex(rgb),
            fill: colorHex(rgb),
            count: 0,
        };
    });

    // 按颜色拆分图层
    for (let i = 0; i < size; i++) {
        const offset = i * 4;
        const rgb = [pixels[offset + 0], pixels[offset + 1], pixels[offset + 2]];
        const alpha = pixels[offset + 3];
        const index = getNearColorIndex(
            rgb,
            layers.map(i => i.rgb)
        );
        const active = layers[index];

        // const distance = layers.map(layer => colorDistance(rgb, layer.rgb));
        // const min = Math.min(...distance);
        // const index = distance.indexOf(min);

        if (alpha > 100 && index >= 0 && active) {
            active.count += 1;
            active.pixel.data[offset] = 0;
            active.pixel.data[offset + 1] = 0;
            active.pixel.data[offset + 2] = 0;
            active.pixel.data[offset + 3] = 255;
        }
    }

    // 生成path
    const promises = layers.map(layer => {
        if (layer.count > 0) {
            layer.ctx.putImageData(layer.pixel, 0, 0);

            const buffer = layer.canvas.toBuffer("image/png");
            console.log("buffer",buffer);
            
            return getSvgPath(layer.width, layer.height, buffer, layer.fill);

            // const buffer = layer.canvas.toBuffer("image/png");
            // const filename = "layer" + layer.color.join("-") + ".png";
            // const filepath = Path.resolve() + "/demo/" + filename;
            // Fs.writeFileSync(filepath, buffer);
            // return Promise.resolve(fullname)
        } else {
            return Promise.resolve("");
        }
    });

    // 下载和预览
    await Promise.all(promises).then(res => {
        const paths = [];
        const colors = [];
        const texts = [];

        const black=null
        
        res.map((i, idx) => {
            const layer = layers[idx];
            if (i && !/d=""/.test(i) && layer) {

                const color = (i.match(/fill="([\w\W]+?)"/) || [])[1];
                const d = (i.match(/d="([\w\W]+?)"/) || [])[1] || "";
                const moves = d.match(/[mM][^mM]+/g);

                console.log("Promise.all:layer",color);

                // if (color == "#22140e") {
                    // paths.push(`<path d="${d} Z" fill="${color}" />`);
                    // paths.push(`<path d="${d} Z" fill="${color}" stroke="white" stroke-width="3" />`);
                    // moves.map(e => paths.push(`<path d="${e} Z" fill="${color}" />`));
                    // moves.map(e => paths.push(`<path d="${e} Z" fill="no" stroke="white" stroke-width="2" />`));
                // } else if (layer.fill == "#fbfbfb") {
                    //
                // } else {
                    // moves.map(e => paths.push(`<path d="${e} Z" fill="${color}" />`));
                    paths.push(`<path d="${d} Z" fill="${color}" />`);
                // }

                // colors.push(`<rect x="10" y="${colors.length * 30 + 10}" width="30" height="20" fill="${layer.fill}" />`);
                // texts.push(`<text x="50" y="${texts.length * 30 + 25}" fill="#f00" stroke-width="1px" stroke="#fff"  paint-order="stroke"  >${layer.fill}</text>`);
            }
        });

        const background = "";
        // const background = `<rect x="0" y="0" width="${width}" height="${height}" fill="#f00" />`;
        const body = [background, paths.join("\n"), colors.join("\n"), texts.join("\n")].join("\n");
        const temp = `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">\n${body}</svg>`;
        const filepath = Path.resolve() + "/demo/embroidery/layer-output.svg";

        Fs.writeFileSync(filepath, temp);
    });
};

// 按图层保存成png图片
const getShapePngs = async (width, height, pixels, colors, place) => {
    const size = width * height;

    // 图层分离
    const layers = colors.map(rgb => {
        const canvas = Canvas.createCanvas(width, height);
        const ctx = canvas.getContext("2d");
        const pixel = ctx.createImageData(width, height);

        return {
            width: width,
            height: height,
            canvas: canvas,
            ctx: ctx,
            pixel: pixel,
            rgb: rgb,
            hex: colorHex(rgb),
            fill: colorHex(rgb),
            count: 0,
        };
    });

    const rgbs = layers.map(i => i.rgb);

    // 按颜色拆分图层
    for (let i = 0; i < size; i++) {
        const offset = i * 4;
        const rgb = [pixels[offset + 0], pixels[offset + 1], pixels[offset + 2]];
        const alpha = pixels[offset + 3];
        const index = getNearColorIndex(rgb, rgbs);
        const active = layers[index];

        // const distance = layers.map(layer => colorDistance(rgb, layer.rgb));
        // const min = Math.min(...distance);
        // const index = distance.indexOf(min);

        layers.map(layer => {
            if (alpha > 100 && index >= 0 && active == layer) {
                layer.count += 1;
                layer.pixel.data[offset] = 255;
                layer.pixel.data[offset + 1] = 255;
                layer.pixel.data[offset + 2] = 255;
                layer.pixel.data[offset + 3] = 255;
            } else {
                layer.pixel.data[offset] = 0;
                layer.pixel.data[offset + 1] = 0;
                layer.pixel.data[offset + 2] = 0;
                layer.pixel.data[offset + 3] = 255;
            }
        });
    }

    // 生成path
    const promises = layers.map(layer => {
        if (layer.count > 0) {
            layer.ctx.putImageData(layer.pixel, 0, 0);

            // const buffer = layer.canvas.toBuffer("image/png");
            // return getSvgPath(layer.width, layer.height, buffer, layer.fill);

            const buffer = layer.canvas.toBuffer("image/png");
            const filename = "layer-output-" + layer.fill + ".png";
            const filepath = Path.resolve() + "/demo/embroidery/" + filename;
            Fs.writeFileSync(filepath, buffer);
            return Promise.resolve(filename);
        } else {
            return Promise.resolve("");
        }
    });

    await Promise.all(promises).then(res => {});
};

// 像素分割
const getShapeImage = async (width, height, pixels, colors) => {
    const size = width * height;

    // 图层分离
    const layers = colors.map(color => {
        const canvas = Canvas.createCanvas(width, height);
        const ctx = canvas.getContext("2d");
        const pixel = ctx.createImageData(width, height);
        return {
            width: width,
            height: height,
            canvas: canvas,
            ctx: ctx,
            pixel: pixel,
            rgb: color.rgb,
            hex: color.hex,
            fill: color.fill,
            count: 0,
        };
    });

    // 相同颜色合并
    for (let i = 0; i < size; i++) {
        const offset = i * 4;
        const rgb = [pixels[offset + 0], pixels[offset + 1], pixels[offset + 2]];
        const alpha = pixels[offset + 3];
        const distance = layers.map(layer => colorDistance(rgb, layer.rgb));
        const min = Math.min(...distance);
        const index = distance.indexOf(min);
        const active = layers[index];

        if (alpha > 100 && index >= 0 && active) {
            const rgb = colorRgb(active.fill);
            active.count += 1;
            active.pixel.data[offset] = rgb[0];
            active.pixel.data[offset + 1] = rgb[1];
            active.pixel.data[offset + 2] = rgb[2];
            active.pixel.data[offset + 3] = 255;
        }
    }

    const canvas = Canvas.createCanvas(width, height);
    const ctx = canvas.getContext("2d");
    const filepath = Path.resolve() + "/demo/embroidery/layer-output.png";

    // 合成path
    layers.map(layer => {
        if (layer.count > 0) {
            layer.ctx.putImageData(layer.pixel, 0, 0);
            // 粘贴图片
            ctx.drawImage(layer.canvas, 0, 0, layer.width, layer.height);
        } else {
            return Promise.resolve("");
        }
    });

    const buffer = canvas.toBuffer("image/png");
    Fs.writeFileSync(filepath, buffer);

    // // 下载和预览
    // await Promise.all(promises).then(res => {
    //     const paths = [];
    //     const colors = [];
    //     res.map((i, idx) => {
    //         const layer = layers[idx];
    //         if (i && !/d=""/.test(i) && layer) {
    //             paths.push(i);
    //             colors.push(`<rect x="10" y="${colors.length * 30}" width="60" height="20" fill="${layer.hex}" />`);
    //         }
    //     });

    //     const temp = `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">\n${paths.join("\n")}\n${colors.join("\n")}</svg>`;
    //     const filepath = Path.resolve() + "/demo/layer-output.svg";

    //     Fs.writeFileSync(filepath, temp);
    // });
};

// const name = "demo/embroidery/cat-transparent.png";
const name = "images/cat-2.png";
// const name = "demo/embroidery/cat-white.png";

// 加载本地资源
loadLocalImage(Path.join(Path.resolve(), name)).then(image => {
    // 取像素
    const pixels = getImageData(image);
    const place = [
        { fill: "#FFFFFF", hex: "#FFFFFF", rgb: [255, 255, 255] },
        { fill: "#000000", hex: "#000000", rgb: [0, 0, 0] },
        { fill: "#96A1A8", hex: "#96A1A8", rgb: [150, 161, 168] },
        { fill: "#A67843", hex: "#A67843", rgb: [166, 120, 67] },
        { fill: "#FFCC00", hex: "#FFCC00", rgb: [255, 204, 0] },
        { fill: "#E25C27", hex: "#E25C27", rgb: [226, 92, 39] },
        { fill: "#CC3366", hex: "#CC3366", rgb: [204, 51, 102] },
        { fill: "#CC3333", hex: "#CC3333", rgb: [204, 51, 51] },
        { fill: "#660000", hex: "#660000", rgb: [102, 0, 0] },
        { fill: "#333366", hex: "#333366", rgb: [51, 51, 102] },
        { fill: "#005397", hex: "#005397", rgb: [0, 83, 151] },
        { fill: "#3399FF", hex: "#3399FF", rgb: [51, 153, 255] },
        { fill: "#6B5294", hex: "#6B5294", rgb: [107, 82, 148] },
        { fill: "#01784E", hex: "#01784E", rgb: [1, 120, 78] },
        { fill: "#7BA35A", hex: "#7BA35A", rgb: [123, 163, 90] },
    ];

    // 取主色
    const colors1 = getBaseColors(pixels, place);
    console.log("colors1",colors1);
    

    // 取主色2
    // const colors2 = gap(pixels, place);

    // console.log("colors2", colors2);

    // slicTest(pixels, image.width, image.height);

    // const colors = place;

    // 按主色，取图形
    getShapePaths(image.width, image.height, pixels, colors1, place);
    // getShapePngs(image.width, image.height, pixels, colors1, place);

    // 按主色，分割图片
    // getShapeImage(image.width, image.height, pixels, colors);

    // console.log(shapes);

    // doLayered(image);
    // getBaseColors(image);
});
